/*
 * @brief Sensor Demo serial I/O information (header file)
 *
 * @note
 * Copyright(C) NXP Semiconductors, 2015
 * All rights reserved.
 *
 * @par
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * LPC products.  This software is supplied "AS IS" without any warranties of
 * any kind, and NXP Semiconductors and its licensor disclaim any and
 * all warranties, express or implied, including all implied warranties of
 * merchantability, fitness for a particular purpose and non-infringement of
 * intellectual property rights.  NXP Semiconductors assumes no responsibility
 * or liability for the use of the software, conveys no license or rights under any
 * patent, copyright, mask work right, or any other intellectual property rights in
 * or to any products. NXP Semiconductors reserves the right to make changes
 * in the software without notification. NXP Semiconductors also makes no
 * representation or warranty that such application will be suitable for the
 * specified use without further testing or modification.
 *
 * @par
 * Permission to use, copy, modify, and distribute this software and its
 * documentation is hereby granted, under NXP Semiconductors' and its
 * licensor's relevant copyrights in the software, without fee, provided that it
 * is used in conjunction with NXP Semiconductors microcontrollers.  This
 * copyright, permission, and disclaimer notice must appear in all copies of
 * this code.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>

#include <time.h>
#include <assert.h>

#include "trace.h"
#include "recorder.h"

/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/
static bool		rec_flag = false;
static FILE*	rec_file = NULL;
static uint32_t	blk_ct;
static uint32_t	byte_ct;

typedef struct {
	char		id[4];
	uint32_t	ver;
	time_t		time;
} FILE_HDR_T;
static const uint32_t file_hdr_sz = sizeof(FILE_HDR_T);

typedef struct {
	uint32_t	tag;
	uint32_t	id;
	uint32_t	size;
} BLOCK_HDR_T;
static const uint32_t blk_hdr_sz = sizeof(BLOCK_HDR_T);

static FILE_HDR_T hdr = {
	{ 'P','K','T','F' },
	0x01020304,
	0
};

#define	BLK_HDR_TAG_DATA		0xaabbccdd
#define	BLK_HDR_TAG_CLOSE		0x00112233

/*****************************************************************************
 * Public types/enumerations/variables
 ****************************************************************************/

/*****************************************************************************
 * Private functions
 ****************************************************************************/

/*****************************************************************************
 * Public functions
 ****************************************************************************/
void rec_init(void)
{
	trace_enter();																/* enter the function */
	rec_flag = false;															/* clear the recording flag */
	blk_ct = 0;																	/* clear block count */
	byte_ct = 0;																/* clear byte count */
	rec_file = NULL;															/* clear the file pointer */
	trace_exit();																/* exit the function */
}

void rec_start(const char* fn)
{
	size_t write_sz=0;

	trace_enter();																/* enter the function */
	rec_file = fopen(fn, "wb");													/* open the file */
	assert(rec_file != NULL);													/* verify it's ok */

	hdr.time = time(NULL);
	write_sz = fwrite(&hdr, file_hdr_sz, 1, rec_file);							/* write the header */
	assert(write_sz == 1);														/* verify write */

	rec_flag = true;															/* set rec flag to true */
	blk_ct = 0;																	/* clear block count */
	byte_ct = 0;																/* clear byte count */
	trace_exit();																/* exit the function */
}

void rec_write_block(const void* blk, uint32_t blk_sz)
{
	BLOCK_HDR_T blk_hdr;
	size_t write_sz=0;

	trace_enter();																/* enter the function */
	if (rec_flag == true) {														/* if recording flag is set */
		blk_ct	+= 1;															/* bump block count */
		byte_ct += blk_sz;														/* bump byte count */

		blk_hdr.tag = BLK_HDR_TAG_DATA;											/* set the tag (used as a check) */
		blk_hdr.id = blk_ct;													/* set the block count */
		blk_hdr.size = blk_sz;													/* set the block size */
		write_sz = fwrite(&blk_hdr, blk_hdr_sz, 1, rec_file);					/* write the block */
		assert(write_sz == 1);													/* verify write */

		write_sz = fwrite(blk, 1, blk_sz, rec_file);							/* write the block */
		assert(blk_sz == write_sz);												/* verify write */
	}
	trace_exit();																/* exit the function */
}

void rec_stop(void)
{
	BLOCK_HDR_T blk_hdr;
	size_t write_sz=0;

	trace_enter();																/* enter the function */
	if (rec_flag == true) {

		blk_hdr.tag = BLK_HDR_TAG_CLOSE;										/* set the tag (used as a check) */
		blk_hdr.id = byte_ct;													/* set the block count */
		blk_hdr.size = 0;														/* set the block size */
		write_sz = fwrite(&blk_hdr, blk_hdr_sz, 1, rec_file);					/* write the block */
		assert(write_sz == 1);													/* verify write */

		fclose(rec_file);														/* close the file */
		rec_flag = false;														/* clear the recording flag */
		blk_ct = 0;																/* clear block count */
		byte_ct = 0;															/* clear byte count */
		rec_file = NULL;														/* clear the file pointer */
	}
	trace_exit();																/* exit the function */
}

bool		rec_get_flag(void)	{	return rec_flag;	}
uint32_t	rec_get_blks(void)	{	return blk_ct;		}
uint32_t	rec_get_bytes(void)	{	return byte_ct;		}
